﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using UIT.Controls.Containers;
using UIT.Controls.Template;
using UIT.Converters;

namespace UIT.Controls.Data
{
    /// <summary>
    /// Modelisation of a column
    /// </summary>
    public class Column
    {
        [System.ComponentModel.TypeConverter(typeof(TemplateConverter))]
        public ITemplate ItemTemplate { get; set; }

        public ITemplate AlternatingItemTemplate { get; set; }

        [System.ComponentModel.TypeConverter(typeof(TemplateConverter))]
        public ITemplate HeaderTemplate { get; set; }

        private string sortExpression;

        public string SortExpression
        {
            get
            {
                if (string.IsNullOrEmpty(sortExpression) && ItemTemplate != null && ItemTemplate.IsBoundTemplate && ItemTemplate.Template.VisualTree != null)
                    sortExpression = ItemTemplate.Template.VisualTree.GetBinding("Text").Path;
                return sortExpression;
            }
            set { sortExpression = value; }
        }

    }

    [ContentProperty("DataGridColumns")]
    public class DataGrid : DrawableControl, IDataConsumer, IContainer
    {
        void DataGrid_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "SortExpression" || e.PropertyName == "PageIndex" || e.PropertyName == "PageSize")
                DataBind();
        }

        /// <summary>
        /// A row is defined by all the Columns on a DataGrid, with a specific DataContext
        /// </summary>
        public class Row : DrawableControl, IContainer
        {
            public Row()
            {
                Children = new ControlCollection(this);
            }

            #region IContainer Members

            public IDisposableObservableCollection<IContainer, IControl> Children
            {
                get;
                private set;
            }

            #endregion

            public override bool IsContainer
            {
                get { return true; }
            }

            public override ControlType Type
            {
                get { return ControlType.TableRow; }
            }

            #region IDisposable Members

            public override void Dispose()
            {
                base.Dispose();
                if (Children != null)
                {
                    Children.Dispose();
                    Children = null;
                }
            }

            #endregion

            public int Index { get; set; }
        }

        public DataGrid()
        {
            DataGridColumns = new List<Column>();
            PageSize = 10;
            PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(DataGrid_PropertyChanged);
        }

        public List<Column> DataGridColumns { get; set; }

        public ControlCollection<Row> Rows
        {
            get;
            private set;
        }

        private IDisposableObservableCollection<IContainer, IControl> children;

        public override bool IsContainer
        {
            get { return true; }
        }

        public override ControlType Type
        {
            get { return ControlType.List; }
        }

        #region IDataConsumer Members

        [System.ComponentModel.TypeConverter(typeof(DataProviderConverter))]
        public IDataProvider DataSource { get; set; }

        #endregion

        #region IContainer Members

        public IDisposableObservableCollection<IContainer, IControl> Children
        {
            get
            {
                if (children == null)
                {
                    DataBind();
                }
                return children;
            }
        }

        private void DataBind()
        {
            if (DataSource != null)
            {
                Rows = new ControlCollection<Row>(this);
                children = new ControlCollectionWrapper<IContainer, Row>(Rows);
                bool takeAlternatingTemplate = false;
                int index = 0;
                var select = new SelectArgument().Page(PageIndex * PageSize, PageSize).Sort(SortExpression);
                var dataSource = DataSource.Select(select);
                TotalRowCount = select.TotalRowCount;
                foreach (var item in dataSource)
                {

                    Row row = new Row();
                    row.DataContext = item;
                    row.Index = index++;
                    foreach (Column column in DataGridColumns)
                    {
                        IControl columnInstance;
                        if (takeAlternatingTemplate && column.AlternatingItemTemplate != null)
                            columnInstance = column.AlternatingItemTemplate.CreateInstance(item);
                        else
                            columnInstance = column.ItemTemplate.CreateInstance(item);

                        if (columnInstance != null)
                            row.Children.Add(columnInstance);
                    }
                    children.Add(row);
                }
                OnPropertyChanged("Rows");
            }
        }

        #endregion

        #region IDisposable Members

        public override void Dispose()
        {
            base.Dispose();
            if (children != null)
            {
                children.Dispose();
                children = null;
            }
        }

        #endregion

        private int pageIndex;

        public int PageIndex
        {
            get { return pageIndex; }
            set
            {
                pageIndex = value;
                OnPropertyChanged("PageIndex");
            }
        }

        private int pageSize;

        public int PageSize
        {
            get { return pageSize; }
            set
            {
                pageSize = value;
                OnPropertyChanged("PageSize");
            }
        }

        private string sortExpression;

        public string SortExpression
        {
            get { return sortExpression; }
            set
            {
                sortExpression = value;
                OnPropertyChanged("SortExpression");
            }
        }

        public int TotalRowCount { get; private set; }
    }
}
